﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "GcmpModelInterface.h"
#include "RegenDataId.h"
#include "IDbObject.h"
#include "IParameter.h"

namespace gcmp {

    class IDocument;
    class IElement;
    class IElementParametersCustomizer;
    class IElementParameterGroupOverride;
    class IParameterOverride;
    class UniIdentity;
    class IElementParameterBindings;
    class ISubComponentPropertyCollection;

    /// \brief 元素参数行为接口
    FINAL_INTERFACE class GCMP_MODEL_INTERFACE_EXPORT IElementParameters : public IDbObject
    {
        DEFINE_CAST_DERIVED(gcmp::IElementParameters, gcmp::IDbObject);

    public:
        /// \brief 生成默认的元素参数行为
        /// \param pDocument 所属文档
        /// \param ownerElementId 所属元素Id
        /// \return 默认的元素参数行为
        static OwnerPtr<IElementParameters> CreateElementParameterBehavior(IDocument* pDocument, 
            const ElementId& ownerElementId);

        /// \brief 设置该行为所属Element
        /// \param pOwnerElement 所属Element
        /// \return 设置成功返回True, 否则返回false
        virtual bool SetOwnerElement(IElement* pOwnerElement) = 0;

        /// \brief 获得该行为所属Element
        /// \return 所属Element
        virtual IElement* GetOwnerElement() = 0;

        /// \brief 获得该行为所属Element
        /// \return 所属Element
        virtual const IElement* GetOwnerElement() const = 0;

    public:
        /// \brief 根据参数id来获得该参数的关联更新数据唯一标识
        /// \param parameterId 参数id
        /// \return 关联更新数据唯一标识
        virtual RegenDataId GetParameterRdId(int parameterId) const = 0;

        /// \brief 获得坐标系系统参数的关联更新数据唯一标识
        /// \return 关联更新数据唯一标识
        virtual RegenDataId GetCoordinateSystemParameterRdId() const = 0;

        /// \brief 获得驱动参数的关联更新数据唯一标识
        /// \return 关联更新数据唯一标识
        virtual RegenDataId GetDriveParameterRdId() const = 0;

        /// \brief 标记驱动参数关联更新变化Id
        /// \return void
        virtual void MarkDriveParameterRdId() = 0;

        /// \brief 标记坐标系系统参数关联更新变化Id
        /// \return void
        virtual void MarkCoordinateSystemParameterRdId() = 0;

        /// \brief 根据参数标记关联更新变化Id
        /// 
        /// 根据参数标记驱动参数、坐标系系统等关联更新变化Id
        /// \param pParameter 参数
        /// \return void
        virtual void MarkParameterRdId(const IParameter *pParameter) = 0;

        /// \brief 设置Element参数定制器
        /// \param 参数自定义行为
        /// \return 如果有旧的参数定制器，返回旧的定制器，如果没有返回空
        virtual OwnerPtr<IElementParametersCustomizer> SetElementParametersCustomizer(
            OwnerPtr<IElementParametersCustomizer> opParametersCustomizer) = 0;

#pragma region ModuleGroup定制
        /// \brief 设置Element参数定制器
        ///
        /// 当希望同时设置当前对象所属的模块组时，使用该接口。
        ///
        /// \param opParametersCustomizer 参数自定义行为
        /// \param moduleGroupGuid 自定义数据所属模块组
        /// \param[out] pResult 设置的结果；设置成功传出true，失败传出false
        /// \return 如果有旧的参数定制器，返回旧的定制器，如果没有返回空
        virtual OwnerPtr<IElementParametersCustomizer> SetElementParametersCustomizer(
            OwnerPtr<IElementParametersCustomizer> opParametersCustomizer, const Guid& moduleGroupGuid, bool* pResult) = 0;

        /// \brief 获取Element参数定制器
        /// \return IElementParametersCustomizer 获取到的参数定制器指针
        virtual IElementParametersCustomizer* GetParametersCustomizer() = 0;

        /// \brief 获取参数自定义行为
        /// \return IElementParametersCustomizer 获取到的参数定制器指针
        virtual const IElementParametersCustomizer* GetParametersCustomizer() const = 0;


        /// \brief 获取ModuleGroup对应的Element参数定制器
        /// \param guid ModuleGroup的guid
        /// \return IElementParametersCustomizer 获取到的参数定制器指针
        virtual IElementParametersCustomizer* GetParametersCustomizer(const Guid& guid) = 0;

        /// \brief 获取ModuleGroup对应的Element参数定制器
        /// \param guid ModuleGroup的guid
        /// \return IElementParametersCustomizer 获取到的参数定制器指针
        virtual const IElementParametersCustomizer* GetParametersCustomizer(const Guid& guid) const = 0;

        /// \brief 获取ModuleGroup对应的Element参数定制器
        /// \param moduleGroups2Customizers ModuleGroup guid到 ParameterCustomizer的映射
        /// \return 成功返回true，失败返回false
        virtual bool GetAllParametersCustomizers(std::map<Guid, IElementParametersCustomizer*>& moduleGroups2Customizers) = 0;

        /// \brief 获取ModuleGroup对应的Element参数定制器
        /// \param moduleGroups2Customizers ModuleGroup guid到 ParameterCustomizer的映射
        /// \return 成功返回true，失败返回false
        virtual bool GetAllParametersCustomizers(std::map<Guid, const IElementParametersCustomizer*>& moduleGroup2Customizer) const = 0;

        /// \brief 删除ModuleGroup对应的Element参数定制器
        /// \param guid ModuleGroup的guid
        /// \return 成功返回true，失败或本身不存在返回false
        virtual bool DeleteParametersCustomizer(const Guid& guid) = 0;

#pragma endregion ModuleGroup定制


        /// \brief 设置参数分组
        /// \param 参数分组行为
        /// \return bool 设置成功(true)or失败(true)
        virtual bool SetElementParameterGroupOverride(
            OwnerPtr<IElementParameterGroupOverride> opParameterGroupOverride) = 0;

        /// \brief 设置参数分组
        ///
        /// 当希望同时设置当前对象所属的模块组时，使用该接口。
        ///
        /// \param opParameterGroupOverride 参数分组行为
        /// \param moduleGroupGuid 自定义数据所属模块组
        /// \return bool 设置成功(true)or失败(true)
        virtual bool SetElementParameterGroupOverride(
            OwnerPtr<IElementParameterGroupOverride> opParameterGroupOverride, const Guid& moduleGroupGuid) = 0;

        /// \brief 参数分组接口
        /// \return 返回参数分组接口
        virtual IElementParameterGroupOverride* GetElementParameterGroupOverride() = 0;

        /// \brief 参数分组接口
        /// \return 返回参数分组接口
        virtual const IElementParameterGroupOverride* GetElementParameterGroupOverride() const = 0;

        /// \brief 设置参数子部件
        /// \param opSubComponentPropertyCollection 要设置的参数子部件
        /// \return bool 成功返回true，失败返回false
        virtual bool SetSubComponentPropertyCollection(OwnerPtr<ISubComponentPropertyCollection> opSubComponentPropertyCollection) = 0;

        /// \brief 获取参数子部件
        /// \return 返回的参数子部件
        virtual const ISubComponentPropertyCollection * GetSubComponentPropertyCollection() const = 0;

        /// \brief 获取参数子部件
        /// \return 返回的参数子部件
        virtual ISubComponentPropertyCollection * GetSubComponentPropertyCollection() = 0;

        /// \brief 获得元素所有的参数信息
        /// \return 元素所有的参数信息
        virtual std::vector<OwnerPtr<IParameter>> GetAllParameters() const = 0;

        /// \brief 根据参数定义Uid检测参数是否存在。
        /// \param parameterDefinitionUid 参数定义Uid
        /// \return 如果参数存在返回true。否则返回false。
        virtual bool HasParameterByUid(const UniIdentity& parameterDefinitionUid) const = 0;

        /// \brief 通过参数定义Uid来获得参数
        /// \param paramDefinitionUid 参数定义Uid
        /// \return 返回IParameter对象，如果失败则返回空的OwnerPtr。
        virtual OwnerPtr<IParameter> GetParameterByUid(const UniIdentity& parameterDefinitionUid) const = 0;

        /// \brief 根据参数id来检测参数是否存在，此参数id文档唯一。
        /// \param parameterId 文档唯一的参数id
        /// \return 如果参数存在返回true。否则返回false。
        virtual bool HasParameterById(int parameterId) const = 0;

        /// \brief 通过参数id来获得参数，此参数id文档唯一。
        /// \param parameterId 文档唯一的参数id
        /// \return 返回IParameter对象，如果失败则返回空的OwnerPtr。
        virtual OwnerPtr<IParameter> GetParameterById(int parameterId) const = 0;

        /// \brief 设置参数
        /// \param pParameter 输入要设置的参数对象
        /// \param errorMessage 输出错误信息，为可选参数。失败的情况下获取错误信息。
        /// \return 返回true表示设置成功，否则表示设置失败。如果失败可以通过errorMessage参数获取错误信息。
        virtual bool SetParameter(const IParameter *pParameter, std::wstring* errorMessage = nullptr) = 0;

        /// \brief 检查参数是否合理
        /// \param pParameter 输入要检查的参数对象
        /// \param errorMessage 输出错误信息，为可选参数。失败的情况下获取错误信息。
        /// \return bool 返回true表示设置成功，否则表示设置失败。如果失败可以通过errorMessage参数获取错误信息。
        virtual bool ValidateParameter(const IParameter *pParameter, std::wstring* errorMessage) = 0;

        /// \brief 获得元素的嵌入式参数映射表
        /// \return 嵌入式参数映射表，Key为文档唯一的参数id，IParameter为参数对象
        virtual const std::map<Int32, OwnerPtr<IParameter>>& GetEmbeddedParametersMap() const = 0;

        /// \brief 获得元素的嵌入式参数映射表
        /// \return 嵌入式参数映射表，Key为文档唯一的参数id，IParameter为参数对象
        virtual std::map<Int32, OwnerPtr<IParameter>>& GetEmbeddedParametersMapFw() = 0;

        /// \brief 根据参数id来获得嵌入式参数对象，此参数id文档唯一。
        /// \param 文档唯一的参数id
        /// \return 参数对象
        virtual const IParameter* GetEmbeddedParameter(int parameterId) const = 0;

        /// \brief 根据参数id来获得嵌入式参数对象，此参数id文档唯一。
        /// \param parameterId 文档唯一的参数id
        /// \return 参数对象
        virtual IParameter* GetEmbeddedParameterFw(int parameterId) = 0;

        /// \brief 添加嵌入式参数
        /// \param pParameter 添加的参数
        /// \param markRdId 表示是否为驱动参数，true表示是驱动参数，false表示为非驱动参数，默认为驱动参数
        /// \return 添加成功返回true，否则返回false
        virtual bool AddEmbeddedParameter(IParameter *pParameter, bool markRdId = true) = 0;

        /// \brief 添加嵌入式参数,产品有自定义参数,并且希望Element对象和自定义数据一起存储时，调用该接口
        ///
        ///如果产品对参数中的IParameterValueStorage或者IParameterValidator有自定义，需要传入自定义参数所在的模块组
        /// \param pParameter 添加的参数
        /// \param moduleGroupGuid 自定义数据所在模块组
        /// \param markRdId 表示是否为驱动参数，true表示是驱动参数，false表示为非驱动参数，默认为驱动参数
        /// \return 添加成功返回true，否则返回false
        virtual bool AddEmbeddedParameter(IParameter *pParameter, const Guid& moduleGroupGuid, bool markRdId = true) = 0;

        /// \brief 通过参数id删除嵌入式参数，此参数id文档唯一。
        /// \param parameterId 文档唯一的参数id
        /// \return 删除成功返回true，否则返回false
        virtual bool DeleteEmbeddedParameter(int parameterId) = 0;

        /// \brief 获得参数绑定集合接口
        /// \return 参数绑定集合接口指针
        virtual const IElementParameterBindings* GetElementParameterBindings() const = 0;

        /// \brief 获得参数绑定集合接口
        /// \return 参数绑定集合接口指针
        virtual IElementParameterBindings* GetElementParameterBindings() = 0;

        /// \brief 报告参数
        /// \param pParameterIds 元素拥有的参数Id集合
        /// \return void 空
        virtual void ReportParameterDefinitions(std::vector<int>* pParameterIds) const = 0;

        /// \brief 获取参数是否可以被修改
        /// \param parameterId 文档唯一的参数id
        /// \return 返回true表示参数可修改，否则返回false。
        virtual bool IsParameterModifiable(int parameterId) const = 0;

        /// \brief 是否是预设的参数，默认都是预设参数
        /// 
        /// \param parameterDefinitionUid 参数定义Uid
        /// \return 返回true表示是预设参数，否则返回false
        virtual bool IsPresetParameter(const UniIdentity& parameterDefinitionUid) const = 0;

        /// \brief 对传入参数值，根据不同的参数类型以及业务场景进行调整过滤
        ///
        /// \param parameterDefinitionUid 参数定义数据Uid
        /// \param values 需要过滤调整的参数值引用
        virtual void FilterParameterValues(const UniIdentity& parameterDefinitionUid, 
            std::vector<OwnerPtr<IParameterValueStorage>>& values) const = 0;

        /// \brief 通过参数id来获得原生参数，此参数id文档唯一。
        /// \param parameterId 文档唯一的参数id
        /// \return 返回IParameter对象，如果失败则返回空的OwnerPtr。
        virtual OwnerPtr<IParameter> GetNativeParameter(int parameterId) const = 0;

        /// \brief 设置原生参数
        /// \param pParameter 输入要设置的参数对象
        /// \param errorMessage 输出错误信息。
        /// \return 返回true表示设置成功，否则表示设置失败。如果失败可以通过errorMessage参数获取错误信息。
        virtual bool SetNativeParameter(const IParameter *pParameter, std::wstring* errorMessage) = 0;


#pragma region 单个参数的行为覆盖
        /// \brief 获取单个参数的行为覆盖(IParameterOverride)
        ///
        /// 单个参数的定制行为通过AddIndividualParameterOverride()加入；通过RemoveIndividualParameterOverride()删除。
        ///
        /// \param parameterUniIdentity 参数的UniIdentity
        /// \return const IParameterOverride * 单个参数的定制行为。返回nullptr表示没有找到对应的IParameterOverride。
        /// \see IParameterOverride, AddIndividualParameterOverride(), RemoveIndividualParameterOverride()
        virtual const IParameterOverride * GetIndividualParameterOverride(
            const UniIdentity & parameterUniIdentity) const = 0;

        /// \brief 加入单个参数的行为覆盖
        ///
        /// 如果已经存同一个参数的行为覆盖，新加入的替换旧的。
        ///
        /// \param opParameterOverride 单个参数的行为覆盖
        /// \return bool 操作是否成功
        /// \see IParameterOverride, GetIndividualParameterOverride(), RemoveIndividualParameterOverride()
        virtual bool AddIndividualParameterOverride(OwnerPtr<IParameterOverride> opParameterOverride) = 0;

        /// \brief 加入单个参数的行为覆盖,产品有自定义参数，并且希望Element对象和自定义数据一起存储时，调用该接口
        ///
        /// 如果已经存同一个参数的行为覆盖，新加入的替换旧的。如果产品对IParameterOverride有自定义，需要传入自定义数据所在的模块组
        ///
        /// \param opParameterOverride 单个参数的行为覆盖
        /// \param moduleGroupGuid 自定义数据所在模块组
        /// \return bool 操作是否成功
        /// \see IParameterOverride, GetIndividualParameterOverride(), RemoveIndividualParameterOverride()
        virtual bool AddIndividualParameterOverride(OwnerPtr<IParameterOverride> opParameterOverride , const Guid& moduleGroupGuid) = 0;

        /// \brief 删除单个参数的定制行为
        ///
        /// \param parameterUniIdentity 参数的UniIdentity
        /// \return bool 操作是否成功
        /// \see IParameterOverride, GetIndividualParameterOverride(), AddIndividualParameterOverride()
        virtual bool RemoveIndividualParameterOverride(const UniIdentity & parameterUniIdentity) = 0;
#pragma endregion

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsString(const UniIdentity& parameterDefinitionUid, std::wstring& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsBool(const UniIdentity& parameterDefinitionUid, bool& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsDouble(const UniIdentity& parameterDefinitionUid, double& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsInt(const UniIdentity& parameterDefinitionUid, int& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsElementId(const UniIdentity& parameterDefinitionUid, ElementId& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsGuid(const UniIdentity& parameterDefinitionUid, Guid& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsColor(const UniIdentity& parameterDefinitionUid, Color& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param hasParameter 表示是否有该参数，如果有返回true，否则返回false
        /// \return OwnerPtr<IParameterCustomData> 返回参数的值
        virtual OwnerPtr<IParameterCustomData> GetParameterValueAsCustomData(const UniIdentity& parameterDefinitionUid,  bool& hasParameter) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefinitionUid 参数的UniIdentity
        /// \param hasParameter 表示是否有该参数，如果有返回true，否则返回false
        /// \return OwnerPtr<IGeometry> 返回参数的值
        virtual OwnerPtr<IGeometry> GetParameterValueAsGeometry(const UniIdentity& parameterDefinitionUid,  bool& hasParameter) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsString(int parameterDefId, std::wstring& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsBool(int parameterDefId, bool& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsDouble(int parameterDefId, double& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsInt(int parameterDefId, int& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsElementId(int parameterDefId, ElementId& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsGuid(int parameterDefId, Guid& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param parameterValue 参数的值
        /// \return bool 如果有该参数返回true，否则返回false
        virtual bool GetParameterValueAsColor(int parameterDefId, Color& parameterValue) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param hasParameter 表示是否有该参数，如果有返回true，否则返回false
        /// \return OwnerPtr<IParameterCustomData> 返回参数的值
        virtual OwnerPtr<IParameterCustomData> GetParameterValueAsCustomData(int parameterDefId, bool& hasParameter) const = 0;

        /// \brief 获取指定参数的值
        ///
        /// \param parameterDefId 参数的Id
        /// \param hasParameter 表示是否有该参数，如果有返回true，否则返回false
        /// \return OwnerPtr<IGeometry> 返回参数的值
        virtual OwnerPtr<IGeometry> GetParameterValueAsGeometry(int parameterDefId, bool& hasParameter) const = 0;
    };

}// namespace gcmp


